#include <iostream>
using namespace std;

/*
在继承关系中，如果子类未实现拷贝构造函数，那么在子类进行拷贝构造操作时，会直接调用父类的拷贝构造函数，如果父类的拷贝构造函数是私有的，则会编译失败。我们有时候也会故意把父类的拷贝构造函数设置为私有的，从而禁止子类的拷贝构造操作。

在继承关系中，如果子类未实现赋值操作重载函数，那么在子类进行赋值操作时，会直接调用父类的赋值操作重载函数，如果父类的赋值操作重载函数是私有的，则会编译失败。我们有时候也会故意把父类的赋值操作重载函数设置为私有的，从而禁止子类进行赋值操作。

一旦子类实现了拷贝构造函数，则在拷贝构造的时候会调用子类的拷贝构造函数和父类的默认构造函数。子类实现了赋值操作重载函数，则只会调用子类的。
*/

class GameBoard {
public:
  GameBoard() { cout << "GameBoard()\n"; }
  
  GameBoard(const GameBoard&) { 
    cout << "GameBoard(const GameBoard&)\n"; 
  }
  
  GameBoard& operator=(const GameBoard&) {
    cout << "GameBoard::operator=()\n";
    return *this;
  }
  
  ~GameBoard() { cout << "~GameBoard()\n"; }
  
};

class Game {
  GameBoard gb; // 组合
  
public:
  // 默认构造
  Game() { cout << "Game()\n"; }
  
  // 拷贝构造
  Game(const Game& g) : gb(g.gb) { 
    cout << "Game(const Game&)\n"; 
  }
  
  // 有参构造
  Game(int) { cout << "Game(int)\n"; }
  
  // 赋值运算
  Game& operator=(const Game& g) {
    gb = g.gb;
    cout << "Game::operator=()\n";
    return *this;
    
  }
  
  class Other {}; // Nested class
  // Automatic type conversion:
  operator Other() const {
    cout << "Game::operator Other()\n";
    return Other();
  }
  
  // 析构函数
  ~Game() { cout << "~Game()\n"; }
  
};

// 子类
class Chess : public Game {};


void f(Game::Other) {}

// 子类
class Checkers : public Game {
public:
  // 默认构造
  Checkers() { cout << "Checkers()\n"; }
  
  // 拷贝构造
  Checkers(const Checkers& c) : Game(c) {
    cout << "Checkers(const Checkers& c)\n";
  }
  
  // 赋值运算
  Checkers& operator=(const Checkers& c) {
    Game::operator=(c);
    cout << "Checkers::operator=()\n";
    return *this;
  }
  
};

int main() {
  Chess d1;  // 默认构造可以继承
  Chess d2(d1); // 拷贝构造可以继承
  
  //! Chess d3(1); // Error: 有参构造无法被继承
  
  d1 = d2; // Operator= synthesized
  f(d1); // Type-conversion IS inherited
  
  Game::Other go;
//!  d1 = go; // Operator= not synthesized 
           // for differing types
            
  Checkers c1, c2(c1);
  c1 = c2;
} ///:~